/**
 * 
 */
package edu.gtcfla.km.repositories.hibernate4;

import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Repository;
import org.vsg.biz.BusinessEntityFactory;
import org.vsg.biz.utils.RepoInjectManager;
import org.vsg.common.orm.hibernate4.HibernateSessionManager;
import org.vsg.common.page.PaginationManager;

import edu.gtcfla.km.UserGroupPermission;
import edu.gtcfla.km.model.UserGroupPermissionD;
import edu.gtcfla.km.model.UserPermissionD;

/**
 * @author Bill Vison
 *
 */
@Repository(value="edu.gtcfla.km.repositories.usergroupPermissionRepo")
public class UserGroupPermissionRepoImpl<T extends UserGroupPermission, ID extends Serializable>  implements edu.gtcfla.km.repositories.UserGroupPermissionRepo<T, ID> {

	
	@Autowired
	private ApplicationContext ctx;
	
	@Autowired	
	private BusinessEntityFactory entityFactory;
	
	@Autowired(required=false)
	private PaginationManager paginationManager;

	private HibernateSessionManager sessionManager;
	

	private static final Logger logger = LoggerFactory.getLogger(UserGroupPermissionRepoImpl.class);

	@Autowired
	public void setSessionFactory(SessionFactory sessionFactory) {
		sessionManager = new HibernateSessionManager(sessionFactory);
	}		

	@Override
	public void save(T entity) {

		Session session = sessionManager.getSession();
	
		if (entity instanceof UserGroupPermissionD) {
			UserGroupPermissionD domainD = (UserGroupPermissionD)entity;

			ID id = (ID)session.save(domainD);
	
 			RepoInjectManager injectManager = new RepoInjectManager(ctx);		
			injectManager.injectSingle(entity);		
		}
		
	}


	
	
	
	@Override
	public void saveAll(Collection<T> entities) {
		Session session = sessionManager.getSession();
		
		for (T entity : entities) {
			if (entity instanceof UserGroupPermissionD) {
				UserGroupPermissionD domainD = (UserGroupPermissionD)entity;

				ID id = (ID)session.save(domainD);
		
	 			RepoInjectManager injectManager = new RepoInjectManager(ctx);		
				injectManager.injectSingle(entity);		
			}			
		}

		
		
	}

	@Override
	public void update(T entity) {
		Session session = sessionManager.getSession();
		
		if (entity instanceof UserPermissionD) {
			UserGroupPermissionD domainD = (UserGroupPermissionD)entity;

			session.update(session.merge(domainD));
	
			RepoInjectManager injectManager = new RepoInjectManager(ctx);		
			injectManager.injectSingle(entity);		
		}		
	}


	@Override
	public void updateAll(Collection<T> entities) {
		// TODO Auto-generated method stub
		Session sess = sessionManager.getSession();

		for (T item : entities) {
			if ( ! ( item instanceof UserGroupPermissionD )) {
				sess.update( sess.merge( item ) );
			} else {
				sess.update (sess.merge( item ));
			}
		}
		
	}


	@Override
	public T findOne(ID primaryKey) {
		Session session = sessionManager.getSession();

		T entity = (T)session.get( UserGroupPermissionD.class, primaryKey);
		RepoInjectManager injectManager = new RepoInjectManager(ctx);		
		injectManager.injectSingle(entity);	
		
		return entity;
	}

	@Override
	public void deleteFully(T entity) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Map<String, T> findUserGroupPermisionByUserGroupIds(Set<String> userIds) {
		
		StringBuilder query = new StringBuilder("select ");
		query.append("entity.id , entity.cateAdding , entity.cateDeleting, entity.cateEditing , entity.categoryId ,");
		query.append("entity.isAdmin , entity.kmAdding , entity.kmDeleting , entity.kmEditing , entity.kmPost , entity.userGroupId ");

		query.append("from ").append(UserGroupPermissionD.class.getName()).append(" as entity ");
		query.append("where entity.userGroupId in (:userGroupIds) ");


		logger.debug("query : " + query.toString());
		
		Session sess = sessionManager.getSession();
		
		Query hql = sess.createQuery( query.toString() );
		hql.setParameterList("userGroupIds", userIds);

		Iterator<Object[]> iterRes = (Iterator<Object[]>) hql.iterate();
		
		Map<String , T>  result = new LinkedHashMap<String ,T>();
		RepoInjectManager injectManager = new RepoInjectManager(ctx);	
		while (iterRes.hasNext()) {
			Object[] fields = iterRes.next();
			
			UserGroupPermissionD entity = new UserGroupPermissionD();
			int i = 0;
			
			entity.setId( (String)fields[i++] );
			entity.setCateAdding( (Short)fields[i++] );
			entity.setCateDeleting( (Short)fields[i++] );
			entity.setCateEditing( (Short)fields[i++] );
			entity.setCategoryId( (String)fields[i++] );
			
			entity.setIsAdmin( (Short)fields[i++] );
			entity.setKmAdding( (Short)fields[i++] );
			entity.setKmDeleting( (Short)fields[i++] );
			entity.setKmEditing( (Short)fields[i++] );
			entity.setKmView( (Short)fields[i++] );
			entity.setUserGroupId((String)fields[i++] );
			
			// --- convert to dto ----
			injectManager.injectSingle( entity );
			
			result.put( entity.getUserGroupId()  , (T)entity);			
			

		}
		return result;

	}

	@Override
	public Map<String, T> findUserGroupPermisionByCateAndUserGroupIds(String categoryId,
			Set<String> userGroupIds) {
		// TODO Auto-generated method stub
		StringBuilder query = new StringBuilder("select ");
		query.append("entity.id , entity.onlyGroupCateView ,  entity.cateAdding , entity.cateDeleting, entity.cateEditing , entity.categoryId ,");
		query.append("entity.isAdmin , entity.kmAdding , entity.kmDeleting , entity.kmEditing , entity.kmPost , entity.userGroupId ");

		query.append("from ").append(UserGroupPermissionD.class.getName()).append(" as entity ");
		query.append("where  entity.categoryId = :categoryId and entity.userGroupId in (:userGroupIds) ");
		
		Set<String> currentUserGroupids = new LinkedHashSet<String>(userGroupIds);
		if (currentUserGroupids.isEmpty()) {
			currentUserGroupids.add("");
		}


		logger.debug("query : " + query.toString());
		
		Session sess = sessionManager.getSession();
		
		Query hql = sess.createQuery( query.toString() );
		hql.setParameter("categoryId", categoryId);
		hql.setParameterList("userGroupIds", currentUserGroupids);

		Iterator<Object[]> iterRes = (Iterator<Object[]>) hql.iterate();
		
		Map<String , T>  result = new LinkedHashMap<String ,T>();
		RepoInjectManager injectManager = new RepoInjectManager(ctx);	
		while (iterRes.hasNext()) {
			Object[] fields = iterRes.next();
			
			UserGroupPermissionD entity = new UserGroupPermissionD();
			int i = 0;
			
			entity.setId( (String)fields[i++] );
			entity.setOnlyGroupCateView( (Short)fields[i++] );
			entity.setCateAdding( (Short)fields[i++] );
			entity.setCateDeleting( (Short)fields[i++] );
			entity.setCateEditing( (Short)fields[i++] );
			entity.setCategoryId( (String)fields[i++] );
			
			entity.setIsAdmin( (Short)fields[i++] );
			entity.setKmAdding( (Short)fields[i++] );
			entity.setKmDeleting( (Short)fields[i++] );
			entity.setKmEditing( (Short)fields[i++] );
			entity.setKmView( (Short)fields[i++] );
			entity.setUserGroupId((String)fields[i++] );
			
			// --- convert to dto ----
			injectManager.injectSingle( entity );
			
			result.put( entity.getUserGroupId()  , (T)entity);			
			

		}
		return result;
	}

	@Override
	public void removeAllByCateUserGroupIds(Set<String> cateIds , Set<String> allIds) {
		// TODO Auto-generated method stub
		StringBuilder query = new StringBuilder("delete ");
		query.append("from KM_USERGROUP_PERM ");
		query.append("where KM_USERGROUP_PERM.category_id in (:cateIds) and  KM_USERGROUP_PERM.usergroup_id in (:ids) ");

		logger.debug("query : " + query.toString());
		
		Session sess = sessionManager.getSession();
		SQLQuery sqlQuery = sess.createSQLQuery(query.toString());
		//Query hql = sess.createQuery( query.toString() );
		if (allIds.isEmpty()) {
			allIds.add("");
		}
		sqlQuery.setParameterList("cateIds", cateIds);
		sqlQuery.setParameterList("ids", allIds);
		
		int updateResult = sqlQuery.executeUpdate();

	}

	
	@Override
	public Map<String, T> findUserGroupPermissionForCategories(String userId) {
		// TODO Auto-generated method stub
		StringBuilder query = new StringBuilder("select ");
		query.append("entity.id , entity.onlyGroupCateView , entity.cateAdding , entity.cateDeleting, entity.cateEditing , entity.categoryId ,");
		query.append("entity.isAdmin , entity.kmAdding , entity.kmDeleting , entity.kmEditing , entity.kmPost , entity.userGroupId ");

		query.append("from ").append(UserGroupPermissionD.class.getName()).append(" as entity ");
		query.append("where  entity.userGroupId = :userGroupId ");


		logger.debug("query : " + query.toString());
		
		Session sess = sessionManager.getSession();
		
		Query hql = sess.createQuery( query.toString() );
		hql.setParameter("userGroupId", userId);

		Iterator<Object[]> iterRes = (Iterator<Object[]>) hql.iterate();
		
		Map<String , T>  result = new LinkedHashMap<String ,T>();
		RepoInjectManager injectManager = new RepoInjectManager(ctx);	
		while (iterRes.hasNext()) {
			Object[] fields = iterRes.next();
			
			UserGroupPermissionD entity = new UserGroupPermissionD();
			int i = 0;
			
			entity.setId( (String)fields[i++] );
			entity.setOnlyGroupCateView( (Short)fields[i++]  );
			entity.setCateAdding( (Short)fields[i++] );
			entity.setCateDeleting( (Short)fields[i++] );
			entity.setCateEditing( (Short)fields[i++] );
			entity.setCategoryId( (String)fields[i++] );
			
			entity.setIsAdmin( (Short)fields[i++] );
			entity.setKmAdding( (Short)fields[i++] );
			entity.setKmDeleting( (Short)fields[i++] );
			entity.setKmEditing( (Short)fields[i++] );
			entity.setKmView( (Short)fields[i++] );
			entity.setUserGroupId( (String)fields[i++] );
			
			// --- convert to dto ----
			injectManager.injectSingle( entity );
			
			result.put( entity.getCategoryId()  , (T)entity);			
			

		}
		return result;
	}

	@Override
	public Map<String, Set<T>> findUserGroupPermisionWithOnlyGroupCateView(
			Set<String> cateIds) {
		// TODO Auto-generated method stub
		StringBuilder query = new StringBuilder("select ");
		query.append("entity.id , entity.onlyGroupCateView ,  entity.cateAdding , entity.cateDeleting, entity.cateEditing , entity.categoryId ,");
		query.append("entity.isAdmin , entity.kmAdding , entity.kmDeleting , entity.kmEditing , entity.kmPost , entity.userGroupId ");

		query.append("from ").append(UserGroupPermissionD.class.getName()).append(" as entity ");
		query.append("where  entity.categoryId in (:categoryIds) and entity.onlyGroupCateView = 1 ");
		
		Set<String> currentCateGroupids = new LinkedHashSet<String>(cateIds);
		if (currentCateGroupids.isEmpty()) {
			currentCateGroupids.add("");
		}


		logger.debug("query : " + query.toString());
		
		Session sess = sessionManager.getSession();
		
		Query hql = sess.createQuery( query.toString() );
		hql.setParameterList("categoryIds", currentCateGroupids);

		Iterator<Object[]> iterRes = (Iterator<Object[]>) hql.iterate();
		
		Map<String , Set<T> >  result = new LinkedHashMap<String ,Set<T>>();
		
		RepoInjectManager injectManager = new RepoInjectManager(ctx);	
		while (iterRes.hasNext()) {
			Object[] fields = iterRes.next();
			
			UserGroupPermissionD entity = new UserGroupPermissionD();
			int i = 0;
			
			entity.setId( (String)fields[i++] );
			entity.setOnlyGroupCateView( (Short)fields[i++] );
			entity.setCateAdding( (Short)fields[i++] );
			entity.setCateDeleting( (Short)fields[i++] );
			entity.setCateEditing( (Short)fields[i++] );
			entity.setCategoryId( (String)fields[i++] );
			
			entity.setIsAdmin( (Short)fields[i++] );
			entity.setKmAdding( (Short)fields[i++] );
			entity.setKmDeleting( (Short)fields[i++] );
			entity.setKmEditing( (Short)fields[i++] );
			entity.setKmView( (Short)fields[i++] );
			entity.setUserGroupId((String)fields[i++] );
			
			// --- convert to dto ----
			injectManager.injectSingle( entity );
			
			
			Set<T> mapSet =  result.get( entity.getCategoryId() );
			if (mapSet == null) {
				mapSet = new LinkedHashSet<T>();
			}
			mapSet.add( (T)entity );
			
			result.put( entity.getCategoryId() , mapSet);			
			

		}
		return result;
	}


	
	
	

	
}
